home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
VObject.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-26
|
20KB
|
991 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "VObject.h"
#include "Class.h"
#include "Menu.h"
#include "Window.h"
#include "WindowSystem.h"
#include "String.h"
#include "PrintManager.h"
#include "ProgEnv.h"
#include "OrdColl.h"
#include "View.h"
#include "Look.h"
#include "Math.h"
Point gBorder(4, 2);
const int cAutoSize = -1;
bool testopen= FALSE;
//---- VObject -----------------------------------------------------------------
NewAbstractMetaImpl(VObject,EvtHandler, (TP(container), T(contentRect)));
VObject::VObject(Rectangle r, int id)
{
SetId(id);
contentRect= r;
container= 0;
SetFlag(eVObjDefault);
if (!testopen)
SetFlag(eVObjOpen);
}
VObject::VObject(int id)
{
SetId(id);
contentRect= gRect0;
container= 0;
SetFlag(eVObjDefault);
if (!testopen)
SetFlag(eVObjOpen);
}
void VObject::FreeAll()
{
Iter next(MakeIterator());
Object *op;
while (op= next())
op->FreeAll();
}
VObject::~VObject()
{
VObject *tmp= container;
container= 0;
if (tmp)
tmp->Remove(this);
}
int VObject::Size()
{
return 0;
}
VObject *VObject::At(int)
{
AbstractMethod("At");
return 0;
}
VObject *VObject::SetAt(int, VObject*)
{
AbstractMethod("SetAt");
return 0;
}
Iterator *VObject::MakeIterator(bool)
{
return new Iterator0;
}
void VObject::Add(VObject*)
{
AbstractMethod("Add");
}
VObject *VObject::Remove(VObject*)
{
AbstractMethod("Remove");
return 0;
}
void VObject::RemoveFromContainer()
{
if (container) {
VObject *tmp= container;
container= 0;
tmp->Remove(this);
}
}
void VObject::SendDown(int id, int part, void *val)
{
Iter next(MakeIterator());
VObject *vop;
while (vop= (VObject*) next())
vop->SendDown(id, part, val);
}
void VObject::CollectParts(Collection* col)
{
Iter next(MakeIterator());
Object *op;
while (op= next())
col->Add(op);
}
//---- state -------------------------------------------------------------------
void VObject::Open(bool mode)
{
SetFlag(eVObjOpen, mode);
if (Size() > 0) {
Iter next(MakeIterator());
VObject *vop;
if (testopen) {
while (vop= (VObject*) next())
if (vop->IsOpen() != mode)
vop->Open(mode);
} else {
while (vop= (VObject*) next())
vop->Open(mode);
}
}
if (TestFlag(eVObjKbdFocus)) {
Window *w= GetWindow();
if (w) {
Manager *m= (Manager*)w->GetNextHandler();
if (m) {
if (mode) {
if (m->GetFirstHandler() == 0) {
m->SetFirstHandler(this);
}
} else {
if (m->GetFirstHandler() == this) {
m->SetFirstHandler(0);
}
}
}
}
}
}
bool VObject::IsOpen()
{
return TestFlag(eVObjOpen);
}
void VObject::Enable(bool b, bool redraw)
{
if ((TestFlag(eVObjEnabled) != 0) != (b != 0)) {
SetFlag(eVObjEnabled, b);
if (redraw)
ForceRedraw();
if (Size() > 0) {
Iter next(MakeIterator());
VObject *vop;
while (vop= (VObject*) next())
vop->Enable(b, FALSE);
}
}
}
void VObject::Highlight(HighlightState hst)
{
bool b= (hst == On);
if (TestFlag(eVObjHighlight) != b) {
SetFlag(eVObjHighlight, b);
ForceRedraw();
}
}
//---- container ---------------------------------------------------------------
void VObject::SetContainer(VObject *v)
{
container= v;
}
void VObject::ClearContainer(VObject *v)
{
if (container && container == v)
container= 0;
}
VObject *VObject::FindContainerOfClass(Class *cla)
{
register VObject *vp;
if (cla == Meta(Window))
vp= this;
else
vp= GetContainer();
for (; vp; vp= vp->GetContainer()) {
if (vp->IsA()->isKindOf(cla))
return vp;
}
return 0;
}
Point VObject::ContainerPoint(Point p)
{
return p;
}
Point VObject::GetPortPoint(Point p)
{
p= ContainerPoint(p);
if (GetContainer())
return GetContainer()->GetPortPoint(p);
return p;
}
Window *VObject::GetWindow()
{
return (Window*) FindContainerOfClass(Meta(Window));
}
View *VObject::GetView()
{
return (View*) FindContainerOfClass(Meta(View));
}
Clipper *VObject::Getclipper()
{
return (Clipper*) FindContainerOfClass(Meta(Clipper));
}
/*
void VObject::AddToClipper(Clipper *clipper)
{
VObject::SetContainer(clipper);
CalcExtent();
SetOrigin(gPoint0);
}
*/
Rectangle VObject::GetViewedRect()
{
return contentRect;
}
void VObject::Focus()
{
if (GetContainer())
GetContainer()->Focus();
}
//---- tree walking ------------------------------------------------------------
VObject *VObject::Detect(BoolFun find, void *arg)
{
if (Size() > 0) {
VObject *g1, *g2;
Iter next(MakeIterator());
while (g1= (VObject*) next())
if (g2= g1->Detect(find, arg))
return g2;
}
if (find(this, this, arg))
return this;
return 0;
}
static bool Comp1(Object*, Object *op, void *v)
{
return (bool) (((VObject*)(op))->GetId() == (int)v);
}
static bool Comp2(Object*, Object *op, void *v)
{
VObject *vop= (VObject*) op;
Point p= *((Point*)v);
return vop->ContainsPoint(p - vop->ContainerPoint(gPoint0));
//return vop->ContainsPoint(p);
}
static bool Comp3(Object*, Object *op, void *v)
{
return op->IsEqual((VObject*)v);
}
static bool Comp4(Object*, Object *op, void *v)
{
return op == (VObject*)v;
}
VObject *VObject::FindItem(int id)
{
if (id != cIdNone)
return Detect(Comp1, (void*) id);
return 0;
}
VObject *VObject::FindItem(Point p)
{
return Detect(Comp2, &p);
}
VObject *VObject::FindItem(VObject *g)
{
return Detect(Comp3, g);
}
VObject *VObject::FindItemPtr(VObject *g)
{
return Detect(Comp4, g);
}
//---- layout ------------------------------------------------------------------
Metric VObject::GetMinSize()
{
if (Size() > 0) {
Metric m;
Iter next(MakeIterator());
VObject *dip;
while (dip= (VObject*) next())
m.Merge(dip->GetMinSize());
return m;
}
return Metric(contentRect.extent);
}
void VObject::CalcExtent()
{
SetExtent(GetMinSize().Extent());
}
int VObject::Base()
{
return GetMinSize().base;
}
void VObject::SetOrigin(Point origin)
{
if (contentRect.origin != origin) {
contentRect.origin= origin;
if (TestFlag(eVObjLayoutCntl))
Control(GetId(), cPartOriginChanged, this);
Object::Send(GetId(), cPartOriginChanged, &origin);
}
}
void VObject::SetExtent(Point extent)
{
if (contentRect.extent != extent) {
contentRect.extent= extent;
if (TestFlag(eVObjLayoutCntl))
Control(GetId(), cPartExtentChanged, this);
// Object::Send(GetId(), cPartExtentChanged, this);
Object::Send(GetId(), cPartExtentChanged, &extent);
}
}
void VObject::ExtentChanged(VObject*)
{
if (GetContainer())
GetContainer()->ExtentChanged(this);
//SetExtent(Max(GetMinSize().Extent(), GetExtent()));
}
void VObject::SetContentRect(Rectangle r, bool redraw)
{
if (!redraw && contentRect == r)
return;
if (redraw)
ForceRedraw();
if (contentRect.extent != r.extent)
SetExtent(r.extent);
SetOrigin(r.origin);
if (redraw)
ForceRedraw();
}
void VObject::Align(Point at, Metric m, VObjAlign a)
{
switch (a & eVObjH) {
case eVObjHLeft:
break;
case eVObjHCenter:
at.x+= (m.Width() - Width())/2;
break;
case eVObjHRight:
at.x+= m.Width() - Width();
break;
}
switch (a & eVObjV) {
case eVObjVBase:
at.y+= m.Base() - Base();
break;
case eVObjVCenter:
at.y+= (m.Height() - Height())/2;
break;
case eVObjVBottom:
at.y+= m.Height() - Height();
break;
}
SetOrigin(at);
}
void VObject::Move(Point delta, bool redraw)
{
if (delta == gPoint0)
return;
if (redraw)
ForceRedraw();
SetOrigin(GetOrigin()+delta);
if (redraw) {
ForceRedraw();
Changed();
}
}
//---- resizing ----------------------------------------------------------------
Command *VObject::GetMover()
{
VObject *v= GetView();
if (v)
return new VObjectMover(this, v->contentRect);
return new VObjectMover(this);
}
Command *VObject::GetStretcher()
{
VObject *v= GetView();
if (v)
return new VObjectStretcher(this, v->contentRect);
return new VObjectStretcher(this);
}
bool VObject::ContainsPoint(Point p)
{
return contentRect.ContainsPoint(p);
}
//---- drawing -----------------------------------------------------------------
void VObject::DrawAll(Rectangle r, bool highlight)
{
if (IsOpen() && r.Clip(contentRect))
DrawInner(r, (bool) (highlight || TestFlag(eVObjHighlight)));
}
void VObject::DrawInner(Rectangle r, bool highlight)
{
if (!GrHasColor())
Draw(r);
if (highlight && ! gPrinting)
DrawHighlight(r);
if (GrHasColor())
Draw(r);
}
void VObject::Draw(Rectangle r)
{
if (Size() > 0) {
Iter next(MakeIterator());
VObject *vop;
while (vop= (VObject*) next())
vop->DrawAll(r, FALSE);
}
}
void VObject::DrawHighlight(Rectangle)
{
gLook->DrawHighlight(contentRect);
}
void VObject::Outline2(Point p1, Point p2)
{
GrStrokeRect(NormRect(p1, p2));
}
void VObject::OutlineRect(Rectangle r)
{
Outline2(r.NW(), r.SE());
}
void VObject::Outline(Point delta)
{
OutlineRect(contentRect+delta);
}
void VObject::RevealRect(Rectangle r, Point minToSee)
{
if (GetContainer())
GetContainer()->RevealRect(r, minToSee);
}
void VObject::RevealAlign(Rectangle r, VObjAlign al)
{
if (GetContainer())
GetContainer()->RevealAlign(r, al);
}
void VObject::Scroll(int mode, Point scroll, bool redraw)
{
if (GetContainer())
GetContainer()->Scroll(mode, scroll, redraw);
}
//---- invalidation and focusing -----------------------------------------------
void VObject::InvalidateRect(Rectangle r)
{
if (r.Clip(contentRect) && IsOpen() && GetContainer())
GetContainer()->InvalidateViewRect(r);
}
void VObject::InvalidateViewRect(Rectangle r)
{
r.origin= ContainerPoint(r.origin);
InvalidateRect(r);
}
void VObject::ForceRedraw()
{
InvalidateRect(contentRect);
}
void VObject::UpdateEvent()
{
gWindowSystem->Update();
}
GrCursor VObject::GetCursor(Point lp)
{
if (GetContainer())
return GetContainer()->GetCursor(ContainerPoint(lp));
return eCrsBoldArrow;
}
//---- input/output ------------------------------------------------------------
OStream& VObject::PrintOn(OStream &s)
{
EvtHandler::PrintOn(s);
return s << contentRect SP;
}
IStream& VObject::ReadFrom(IStream &s)
{
EvtHandler::ReadFrom(s);
s >> contentRect;
container= 0;
return s;
}
//---- input handling ----------------------------------------------------------
EvtHandler *VObject::GetNextHandler()
{
return GetContainer();
}
void VObject::DoTrackMouse(TrackPhase atp, Point)
{
if (Enabled()) {
switch (atp) {
case eTrackPress:
Highlight(On);
break;
case eTrackRelease:
Control(GetId(), cPartToggle, (void*) 1);
case eTrackExit:
Highlight(Off);
break;
default:
break;
}
}
}
void VObject::ReadEvent(Token &t, int timeout, bool overread)
{
if (GetContainer())
GetContainer()->ReadEvent(t, timeout, overread);
}
Command *VObject::Input(Point lp, Token &t, Clipper *vf)
{
if (t.IsKey() || t.IsFunctionKey() || t.IsCursorKey() || ContainsPoint(lp)) {
if (Enabled()) {
if (TestFlag(eVObjKbdFocus) && t.Code == eEvtLeftButton
&& !(t.Flags & eFlgButDown)) {
GetWindow()->SetFirstHandler(this);
}
return DispatchEvents(lp, t, vf);
}
return gNoChanges;
}
return 0;
}
Command *VObject::DispatchEvents(Point lp, Token &t, Clipper *vf)
{
register Command *currCmd;
if (Size() > 0) {
Iter previous(MakeIterator(FALSE));
VObject *dip;
while (dip= (VObject*) previous())
if (currCmd= dip->Input(lp, t, vf))
return currCmd;
}
currCmd= gNoChanges;
if (t.IsMouseButton() || t.Code == eEvtLocMove || t.Code == eEvtLocStill)
GrSetCursor(GetCursor(lp));
switch (t.Code) {
case eEvtRightButton:
if (!(t.Flags & eFlgButDown))
currCmd= DoRightButtonDownCommand(lp, t, WindowSystem::Clicks, vf);
break;
case eEvtMiddleButton:
case eEvtLeftButton:
if (!(t.Flags & eFlgButDown)) {
if (t.Code == eEvtLeftButton) {
if (t.Flags == (eFlgShiftKey|eFlgCntlKey|eFlgMetaKey))
gProgEnv->InspectClick(this);
else
currCmd= DoLeftButtonDownCommand(lp, t, WindowSystem::Clicks);
} else
currCmd= DoMiddleButtonDownCommand(lp, t, WindowSystem::Clicks);
if (currCmd && currCmd != gNoChanges && vf)
currCmd= vf->TrackInContent(lp, t, currCmd);
}
break;
default:
if (t.IsKey())
currCmd= DoKeyCommand(t.Code, t);
else if (t.IsFunctionKey())
currCmd= DoFunctionKeyCommand(t.FunctionCode(), t);
else if (t.IsCursorKey())
currCmd= DoCursorKeyCommand(t.CursorDir(), t);
else if (t.Code == eEvtIdle)
currCmd= DoIdleCommand();
else
currCmd= DoOtherEventCommand(lp, t);
break;
}
return currCmd;
}
Command *VObject::DoKeyCommand(int ch, Token t)
{
if (GetContainer())
return GetContainer()->DoKeyCommand(ch, t);
return gNoChanges;
}
Command *VObject::DoCursorKeyCommand(EvtCursorDir d, Token t)
{
if (GetContainer())
return GetContainer()->DoCursorKeyCommand(d, t);
return gNoChanges;
}
Command *VObject::DoFunctionKeyCommand(int pfk, Token t)
{
int code= -1;
switch (t.FunctionCode()) {
case 3:
code= cUNDO;
break;
case 5:
code= cCOPY;
break;
case 4:
code= cTOP;
break;
case 7:
code= cPASTE;
break;
case 9:
code= cCUT;
break;
case 8:
code= cFIND;
break;
case 6:
code= cOPEN;
break;
}
if (code > 0)
return DoMenuCommand(code);
if (GetContainer())
return GetContainer()->DoFunctionKeyCommand(pfk, t);
return gNoChanges;
}
Command *VObject::DoMiddleButtonDownCommand(Point p, Token t, int clicks)
{
if (GetContainer())
return GetContainer()->DoMiddleButtonDownCommand(ContainerPoint(p), t, clicks);
return gNoChanges;
}
Command *VObject::DoLeftButtonDownCommand(Point p, Token t, int clicks)
{
if (GetContainer())
return GetContainer()->DoLeftButtonDownCommand(ContainerPoint(p), t, clicks);
return gNoChanges;
}
Command *VObject::DoOtherEventCommand(Point p, Token t)
{
if (GetContainer())
return GetContainer()->DoOtherEventCommand(ContainerPoint(p), t);
return gNoChanges;
}
Command *VObject::DoRightButtonDownCommand(Point lp, Token, int, Clipper *vf)
{
if (vf) {
Menu *menu= GetMenu();
if (menu) {
int cmdno;
if ((cmdno= menu->Pulldown(lp, vf)) >= 0) { // show menu in window
vf->Focus();
if (gFirstHandler) {
EvtHandler *old= gFirstHandler;
Command *cmd= gFirstHandler->DoMenuCommand(cmdno);
gFirstHandler= old;
gFirstHandler->PerformCommand(cmd);
} else
PerformCommand(DoMenuCommand(cmdno));
// return DoMenuCommand(cmdno);
}
}
}
return gNoChanges;
}
Command *VObject::TrackInContent(Point lp, Token t, Command *currCmd)
{
if (GetContainer())
return GetContainer()->TrackInContent(ContainerPoint(lp), t, currCmd);
return currCmd;
}
//---- misc --------------------------------------------------------------------
void VObject::Print()
{
gPrintManager->ShowPrintDialog(this);
}
//---- VObjectCommand ----------------------------------------------------------
VObjectCommand::VObjectCommand(VObject *g) : Command(cIdNone)
{
vop= g;
SetFlag(eCmdNoReplFeedback);
}
void VObjectCommand::Init(VObject *g, Rectangle cr, Point gr, GrCursor cd, int hy)
{
vop= g;
constrainRect= cr;
grid= gr;
newcursor= cd;
firstmove= FALSE;
hysterese= hy;
oldRect= newRect= vop->ContentRect();
}
Command *VObjectCommand::TrackMouse(TrackPhase atp, Point ap, Point, Point np)
{
switch (atp) {
case eTrackPress:
oldcursor= GrGetCursor();
break;
case eTrackRelease:
GrSetCursor(oldcursor);
if (firstmove) {
if (vop->GetView() && !TestFlag(eCmdFullScreen))
vop->SetContentRect(oldRect, FALSE);
break;
}
return gNoChanges;
case eTrackMove:
delta= np - ap;
if (Math::Abs(delta.x) > hysterese || Math::Abs(delta.y) > hysterese) {
firstmove= TRUE;
GrSetCursor(newcursor);
}
break;
default:
break;
}
return this;
}
void VObjectCommand::TrackConstrain(Point ap, Point, Point *np)
{
Rectangle r= oldRect;
r.origin+= *np-ap;
*np+= r.AmountToTranslateWithin(constrainRect);
if (grid >= 1)
*np= (*np/grid) * grid; // align to grid
}
void VObjectCommand::TrackFeedback(Point, Point, bool on)
{
if (firstmove) {
if (GrGetPenInk() != ePatXor) {
if (on)
vop->SetContentRect(newRect, TRUE);
} else
vop->Outline2(newRect.NW(), newRect.SE());
}
}
void VObjectCommand::DoIt()
{
vop->SetContentRect(newRect, !TestFlag(eCmdFullScreen));
}
void VObjectCommand::UndoIt()
{
vop->SetContentRect(oldRect, !TestFlag(eCmdFullScreen));
}
//---- VObjectMover ------------------------------------------------------------
VObjectMover::VObjectMover(VObject *g) : VObjectCommand(g)
{
Init(g, gRect0, gPoint1, eCrsMoveHand, 2);
}
VObjectMover::VObjectMover(VObject *g, Rectangle cr) : VObjectCommand(g)
{
Init(g, cr, gPoint1, eCrsMoveHand, 2);
}
VObjectMover::VObjectMover(VObject *g, Rectangle cr, Point gr, GrCursor cd,
int hy) : VObjectCommand(g)
{
Init(g, cr, gr, cd, hy);
}
void VObjectMover::Init(VObject *g, Rectangle cr, Point gr, GrCursor cd, int hy)
{
SetName("move");
VObjectCommand::Init(g, cr, gr, cd, hy);
}
Command *VObjectMover::TrackMouse(TrackPhase atp, Point ap, Point pp, Point np)
{
Command *cmd= VObjectCommand::TrackMouse(atp, ap, pp, np);
switch (atp) {
case eTrackMove:
newRect= oldRect;
newRect.origin+= delta;
return this;
case eTrackRelease:
if (newRect == oldRect) {
if (vop->IsKindOf(Window))
((Window*)vop)->Top();
cmd= gNoChanges;
}
break;
default:
break;
}
return cmd;
}
//---- VObjectStretcher --------------------------------------------------------
VObjectStretcher::VObjectStretcher(VObject *g) : VObjectCommand(g)
{
Init(g, gRect0, gPoint1, eCrsMoveStretch, 2, g->GetMinSize());
}
VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr) : VObjectCommand(g)
{
Init(g, cr, gPoint1, eCrsMoveStretch, 2, g->GetMinSize());
}
VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr, Point ms) : VObjectCommand(g)
{
Init(g, cr, ms, eCrsMoveStretch, 2, g->GetMinSize());
}
VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr, Point ms, Point gr,
GrCursor cd, int hy) : VObjectCommand(g)
{
Init(g, cr, gr, cd, hy, ms);
}
void VObjectStretcher::Init(VObject *g, Rectangle cr, Point gr,
GrCursor cd, int hy, Point ms)
{
SetName("resize");
VObjectCommand::Init(g, cr, gr, cd, hy);
minSize= ms;
}
void VObjectStretcher::TrackConstrain(Point ap, Point, Point *np)
{
switch (corner) {
case 0: case 4:
np->x= ap.x;
break;
case 2: case 6:
np->y= ap.y;
break;
}
}
Command *VObjectStretcher::TrackMouse(TrackPhase atp, Point ap, Point pp, Point np)
{
Point p1, p2;
switch (atp) {
case eTrackPress:
VObjectCommand::TrackMouse(atp, ap, pp, np);
corner= oldRect.PointToCorner(ap);
break;
case eTrackMove:
VObjectCommand::TrackMouse(atp, ap, pp, np);
p1= oldRect.NW();
p2= oldRect.SE();
switch (corner) {
case 0: case 6: case 7:
p1+= delta;
break;
case 1:
p2.x+= delta.x;
p1.y+= delta.y;
break;
case 5:
p1.x+= delta.x;
p2.y+= delta.y;
break;
default: // case 2: case 3: case 4:
p2+= delta;
break;
}
newRect= NormRect(p1, p2);
newRect.extent= Max(newRect.extent, minSize);
break;
case eTrackRelease:
return VObjectCommand::TrackMouse(atp, ap, pp, np);
default:
break;
}
return this;
}